package com.cmcc.groupcontacts.base;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.cmcc.groupcontacts.MainApp;
import com.cmcc.groupcontacts.database.DatabaseAdapter;
import com.cmcc.groupcontacts.util.ExceptionHandler;

/**
 * SQLite数据库访问抽象基类
 * 
 * @author 
 * 
 */
public abstract class BaseDAO<T extends BaseModel> {
	protected DatabaseAdapter dba;
	protected String tableName;

	protected BaseDAO(String tableName) {
		this(MainApp.instance, tableName);
	}

	protected BaseDAO(Context context, String tableName) {
		dba = new DatabaseAdapter(context);
		this.tableName = tableName;
	}

	public long add(BaseModel bean) {
		SQLiteDatabase db = null;
		long id = 0;
		try {
			db = dba.getWriteDbInstance();
			id = db.insert(tableName, null, bean.getContentValues());
		} finally {
			dba.close(db);
		}
		return id;
	}

	public void batchAdd(List<T> list) {
		SQLiteDatabase db = dba.getWriteDbInstance();
		if (list != null) {
			db.beginTransaction();
			try {
				for (T bean : list) {
					db.insert(tableName, null, bean.getContentValues());
				}
				db.setTransactionSuccessful();
			} finally {
				db.endTransaction();
			}
		}
		dba.close(db);
	}

	public long del(String whereClause, String[] args) {
		SQLiteDatabase db = null;
		long i = 0;
		try {
			db = dba.getWriteDbInstance();
			i = db.delete(tableName, whereClause, args);
		} finally {
			dba.close(db);
		}
		return i;
	}

	public int update(BaseModel bean, String whereClause, String[] args) {
		SQLiteDatabase db = null;
		int i;
		try {
			db = dba.getWriteDbInstance();
			i = db.update(tableName, bean.getContentValues(), whereClause, args);
		} finally {
			dba.close(db);
		}
		return i;
	}

	public int update(ContentValues cv, String whereClause, String[] args) {
		SQLiteDatabase db = null;
		int i;
		try {
			db = dba.getWriteDbInstance();
			i = db.update(tableName, cv, whereClause, args);
		} finally {
			dba.close(db);
		}
		return i;
	}

	/**
	 * 根据条件查找一个VO对象
	 * 
	 * @param whereClause
	 * @param args
	 * @return
	 */
	public T find(String whereClause, String[] args) {
		SQLiteDatabase db = dba.getReadDbInstance();
		Cursor c = null;
		T bean = null;
		try {
			c = db.query(tableName, getBeanAllCols(), whereClause, args, null, null, null);
			if (c != null && c.moveToNext()) {
				bean = getInstance();
				parse2Bean(c, getBeanAllCols(), bean);
			}
		} catch (Exception e) {
			ExceptionHandler.handle(e);
		} finally {
			if (c != null)
				c.close();
			dba.close(db);
		}
		return (T) bean;
	}

	/**
	 * 根据条件查找指定字节流项的值
	 * 
	 * @param columnName
	 * @param whereClause
	 * @param args
	 * @return
	 */
	public byte[] findBytes(String columnName, String whereClause, String[] args) {
		SQLiteDatabase db = dba.getReadDbInstance();
		Cursor c = null;
		try {
			c = db.query(tableName, new String[] { columnName }, whereClause, args, null, null, null);
			if (c != null && c.moveToNext()) {
				return c.getBlob(c.getColumnIndex(columnName));
			} else {
				return null;
			}
		} finally {
			if (c != null && !c.isClosed()) {
				c.close();
			}
			dba.close(db);
		}
	}

	/**
	 * 获取VO对象的一个实例
	 * 
	 * @return
	 */
	protected abstract T getInstance();

	/**
	 * 获取VO对象对应数据库表的所有列
	 * 
	 * @return
	 */
	protected abstract String[] getBeanAllCols();

	public ArrayList<T> query(boolean distinct, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) {
		SQLiteDatabase db = dba.getReadDbInstance();
		Cursor c = null;
		ArrayList<T> list;
		try {
			c = db.query(distinct, tableName, columns, selection, selectionArgs, groupBy, having, orderBy, limit);
			list = parse2Beans(c, columns);
		} finally {
			if (c != null)
				c.close();
			dba.close(db);
		}
		return list;

	}

	public ArrayList<T> query(String sql) {
		SQLiteDatabase db = dba.getReadDbInstance();
		Cursor c = null;
		ArrayList<T> list;
		try {
			c = db.rawQuery(sql, null);
			list = parse2Beans(c);
		} finally {
			if (c != null)
				c.close();
			dba.close(db);
		}
		return list;
	}

	/**
	 * 获取表中记录的每一列后回调,用于设置实体bean属性
	 * 
	 * @param bean
	 *            实体bean对象
	 * @param colName
	 *            列名
	 * @param value
	 *            列的值
	 */
	protected void afterGetColValue(BaseModel bean, String colName, String value) {
	}

	protected T parse2Bean(Cursor c, String[] cols, T bean) {
		String value;
		if (c != null) {
			for (int i = 0; i < cols.length; i++) {
				value = c.getString(c.getColumnIndex(cols[i].toLowerCase()));
				// bean.putValue(cols[i], value);
				afterGetColValue(bean, cols[i], value);
			}
		}
		return bean;
	}

	protected ArrayList<T> parse2Beans(Cursor c) {
		return parse2Beans(c, null);
	}

	protected ArrayList<T> parse2Beans(Cursor c, String[] cols) {
		if (cols == null || cols.length == 0) {
			cols = getBeanAllCols();
		}

		ArrayList<T> list = new ArrayList<T>();
		T bean;
		if (c != null && c.moveToFirst()) {
			int count = c.getCount();
			for (int i = 0; i < count; i++) {
				bean = getInstance();
				list.add(parse2Bean(c, cols, bean));
				c.moveToNext();
			}
		}
		return list;
	}

	public int getCount(String selection, String[] selectionArgs, String groupBy, String having, String limit) {
		SQLiteDatabase db = dba.getReadDbInstance();
		Cursor c = null;
		try {
			c = db.query(false, tableName, new String[] { "1" }, selection, selectionArgs, groupBy, having, null, limit);
			if (c != null) {
				return c.getCount();
			} else {
				return 0;
			}
		} finally {
			if (c != null)
				c.close();
			dba.close(db);
		}
	}

	public ArrayList<T> load() {
		SQLiteDatabase db = dba.getReadDbInstance();
		Cursor c = null;
		ArrayList<T> list;
		try {
			c = db.rawQuery("select * from " + tableName, null);
			list = parse2Beans(c);
		} finally {
			if (c != null)
				c.close();
			dba.close(db);
		}
		return list;
	}

	public ArrayList<T> load(String orderBy, boolean isDesc) {
		SQLiteDatabase db = dba.getReadDbInstance();
		Cursor c = null;
		ArrayList<T> list;
		try {
			c = db.rawQuery("select * from " + tableName + " " + orderBy + (isDesc ? " desc" : ""), null);
			list = parse2Beans(c);
		} finally {
			if (c != null)
				c.close();
			dba.close(db);
		}
		return list;
	}
	
	public T get(int id) {
		SQLiteDatabase db = dba.getReadDbInstance();
		Cursor c = null;
		T bean = null;
		try {
			c = db.query(tableName, getBeanAllCols(), "id=?", new String[]{String.valueOf(id)}, null, null, null);
			if (c != null && c.moveToNext()) {
				bean = getInstance();
				parse2Bean(c, getBeanAllCols(), bean);
			}
		} catch (Exception e) {
			ExceptionHandler.handle(e);
		} finally {
			if (c != null)
				c.close();
			dba.close(db);
		}
		return (T) bean;
	}
	
	public int update(BaseModel bean) {
		SQLiteDatabase db = null;
		int i;
		try {
			db = dba.getWriteDbInstance();
			i = db.update(tableName, bean.getContentValues(), "id=?", new String[]{String.valueOf(bean.id)});
		} finally {
			dba.close(db);
		}
		return i;
	}
	
	public long delete(int id) {
		SQLiteDatabase db = null;
		long i = 0;
		try {
			db = dba.getWriteDbInstance();
			i = db.delete(tableName, "id=?", new String[]{String.valueOf(id)});
		} finally {
			dba.close(db);
		}
		return i;
	}
}
